package cn.py.boot_lua.service;

import cn.py.boot_lua.util.HttpUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.core5.http.HttpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;

@Slf4j
@Component
public class TalkService {
    @Autowired
    @Qualifier("scheduledExecutor")
    private ScheduledExecutorService executor;
    private <T> CompletableFuture<T> executeForResult(
            Callable<T> task, Predicate<T> isComplete, int pollIntervalMillis, int maxAttempts) {

        CompletableFuture<T> future = new CompletableFuture<>();
        AtomicInteger attempt = new AtomicInteger(0);
        AtomicReference<ScheduledFuture<?>> futureRef = new AtomicReference<>();

        Runnable pollingTask = () -> {
            try {
                if (future.isDone()) {
                    cancelAndLog(futureRef.get());
                    return;
                }
                int currentAttempt = attempt.incrementAndGet();
                if (currentAttempt > maxAttempts) {
                    String errorMsg = "轮询任务达到最大尝试次数: " + maxAttempts;
                    log.warn(errorMsg);
                    future.completeExceptionally(new RuntimeException(errorMsg));
                    cancelAndLog(futureRef.get());
                    return;
                }
                T result = task.call();
                boolean completed;
                try {
                    completed = result != null && isComplete.test(result);
                } catch (Exception e) {
                    log.error("predicate 执行失败", e);
                    future.completeExceptionally(e);
                    cancelAndLog(futureRef.get());
                    return;
                }
                if (completed) {
                    future.complete(result);
                    cancelAndLog(futureRef.get());
                    log.info("轮询任务成功完成，结果: {}", result);
                } else {
                    log.debug("轮询任务尚未完成，当前尝试次数: {}", currentAttempt);
                }

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 保留中断状态
                future.completeExceptionally(e);
                cancelAndLog(futureRef.get());
                log.warn("轮询任务被中断", e);
            } catch (Exception e) {
                Throwable cause = e instanceof ExecutionException && e.getCause() != null ? e.getCause() : e;
                future.completeExceptionally(cause);
                cancelAndLog(futureRef.get());
                log.error("轮询任务发生异常", cause);
            }
        };
        ScheduledFuture<?> scheduled = executor.scheduleAtFixedRate(pollingTask, 0, pollIntervalMillis, TimeUnit.MILLISECONDS);
        futureRef.set(scheduled);
        future.whenComplete((result, ex) -> cancelAndLog(futureRef.get()));
        return future;
    }

    private void cancelAndLog(ScheduledFuture<?> future) {
        if (future != null && !future.isCancelled()) {
            future.cancel(false);
            log.debug("任务已取消");
        }
    }

    private JSONObject queryTaskStatus(String requestPath, String taskId, Map<String, String> headers) {
        try {
            String doGet = HttpUtils.doGet(requestPath + taskId, new HashMap<>(), headers);
            JSONObject jsonObject = JSON.parseObject(doGet);
            return jsonObject.getJSONObject("output");
        } catch (Exception e) {
            log.error("查询任务状态失败", e);
            throw new RuntimeException("查询任务状态异常", e);
        }
    }

    public void runExcut(String requestPath, String taskId){
        try {
            Map<String, String> headers = new HashMap<>();
            headers.put(HttpHeaders.AUTHORIZATION, "Bearer " + "111111111111111111");
            Callable<JSONObject> task = () -> queryTaskStatus(requestPath, taskId, headers);
            Predicate<JSONObject> isDone = output -> "SUCCEEDED".equals(output.getString("task_status"));
            CompletableFuture<JSONObject> future = executeForResult(task, isDone, 15000, 20);
            List<String> list = processImagesAsync(future).get();
            System.out.println("阻塞得到的结果: " + list);
        }catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    private CompletableFuture<List<String>> processImagesAsync(CompletableFuture<JSONObject> future) {
        return future.thenApply(output -> {
                    JSONArray jsonArray = output.getJSONArray("results");
                    List<String> imgList = new ArrayList<>();
                    for (Object tem : jsonArray) {
                        JSONObject t = JSON.parseObject(tem.toString());
                        String imageUrl = Optional.ofNullable(t.getString("url")).orElse("");
                        imgList.add(imageUrl);
                    }
                    return imgList;
                })
                .exceptionally(ex -> {
                    log.error("任务执行失败", ex);
                    return Collections.emptyList();
                });
    }


    //
    private void process(CompletableFuture<JSONObject> future) {
        future.thenApply(output -> {
                    JSONArray jsonArray = output.getJSONArray("results");
                    List<String> imgList = new ArrayList<>();
                    for (Object tem : jsonArray) {
                        JSONObject t = JSON.parseObject(tem.toString());
                        String imageUrl = Optional.ofNullable(t.getString("url")).orElse("");
                        imgList.add(imageUrl);
                    }
                    return imgList;
                })
                .exceptionally(ex -> {
                    log.error("任务执行失败", ex);
                    return Collections.emptyList();
                })
                .thenAccept(imgPaths -> {
                    log.info("data value: " + imgPaths);
                });
    }

}
